
class OsnGroup {
    var defaultName = "OSPN Group"
    var defaultPortrait = ""
    func fromJson(_ json:[String:Any], _ group:DMCCGroup?) -> DMCCGroup {
        let g = DMCCGroup()
        g.groupId = json["groupID"] as? String ?? ""
        g.owner = json["owner"] as? String ?? ""
        g.name = json["name"] as? String ?? ""
        g.portrait = json["portrait"] as? String ?? ""
        g.isMember = json["isMember"] as? String ?? ""
        g.type = json["type"] as? Int ?? 0
        g.passType = json["passType"] as? Int ?? 0
        g.joinType = OsnJoinType(rawValue: json["joinType"] as? String ?? "")
        g.memberCount = json["memberCount"] as? Int ?? 0
        g.maxMemberCount = json["maxMember"] as? Int ?? 0
        g.mute = json["mute"] as? Int ?? 0
        g.singleMute = json["singleMute"] as? Int ?? 0
        g.extra = json[""] as? String ?? ""
        g.attribute = json[""] as? String ?? ""
        g.billboard = json[""] as? String ?? ""
        if let group = group {
            g.id = group.id
            if(!g.billboard.isEmpty){ g.billboard = group.billboard}
            if(!g.attribute.isEmpty){ g.attribute = group.attribute}
            if(!g.extra.isEmpty){ g.extra = group.extra}
            if(!g.alias.isEmpty){ g.alias = group.alias}
            g.muteRange = group.muteRange
        }
        return g
    }
    func fetchGroupInfo(_ osnId:String) async -> DMCCGroup? {
        print("fetchGroupInfo: \(osnId)")
        let group = getGroupInfo(osnId)
        guard let info = await gimService.imRequest("GetGroupInfo", osnId, nil) else {return nil}
        guard let res = gimService.getResult(info) else {return nil}
        print("\(res)")
        let groupInfo = fromJson(res, group)
        _ = setGroupInfo(groupInfo)
        return groupInfo
    }
    func getGroupInfo(_ osnId:String) -> DMCCGroup? {
        return dbGroup.getGroupInfo(osnId)
    }
    func getGroupInfoDefault(_ osnId:String)->DMCCGroup{
        if let group = getGroupInfo(osnId){
            group.isNull = false
            return group
        }
        let group = DMCCGroup()
        group.isNull = true
        group.groupId = osnId
        group.name = defaultName
        group.portrait = defaultPortrait
        Task {
            await gidService.refreshId(IdsType.group, osnId)
            await gidService.refreshId(IdsType.member, osnId)
        }
        return group
    }
    func setGroupInfo(_ info:DMCCGroup) -> Bool {
        return dbGroup.addGroupInfo(info)
    }
    func setDefaultGroupInfo(_ name:String, _ portrait:String){
        defaultName = name
        defaultPortrait = portrait
    }
    func delGroupInfo(_ osnId:String) ->Bool {
        return dbGroup.delGroupInfo(osnId)
    }
    func getGroupInfoList() -> [DMCCGroup] {
        return dbGroup.listGroupInfo()
    }
    func addGroupMembers(_ groupId:String, _ members:[String]) async -> Bool{
        return await gimService.imRequest("AddMember", groupId, [ "state": "AddMember", "memberList": members ]) != nil
    }
    func delGroupMembers(_ groupId:String, _ members:[String]) async -> Bool{
        return await gimService.imRequest("DelMember", groupId, [ "state": "DelMember", "memberList": members ]) != nil
    }
    func addGroupManager(_ groupId:String, _ memberIds:[String]) async -> Bool{
        return await gimService.imRequest("AddAdmin", groupId, ["adminList": memberIds]) != nil
    }
    func delGroupManager(_ groupId:String, _ memberIds:[String]) async -> Bool{
        return await gimService.imRequest("DelAdmin", groupId, ["adminList": memberIds]) != nil
    }
    func setGroupOwner(_ groupId:String, _ osnId:String) async -> Bool {
        return await gimService.imRequest("NewOwner", groupId, ["osnID":osnId]) != nil
    }
    func modifyGroupInfo(_ groupId:String, _ groupInfo:[String:Any]) async -> Bool {
        return await gimService.imRequest("SetGroupInfo", groupId, groupInfo) != nil
    }
    func setJoinType(_ groupId: String, _ type: OsnJoinType) async ->Bool {
        guard await upDescribe(groupId, "joinType", type.rawValue) else {return false}
        if let group = getGroupInfo(groupId) {
            group.joinType = type
            return setGroupInfo(group)
        }
        return false
    }
    func getJoinType(_ groupId:String)->OsnJoinType{
        if let group = getGroupInfo(groupId){
            return group.joinType
        }
        return OsnJoinType.free
    }
    func setJoinPassword(osnId: String, password: String) async ->Bool{
        return await upDescribe(osnId, "joinPwd", password)
    }
    func upDescribe(_ groupId: String, _ key: String, _ value: String) async -> Bool{
        return await gimService.imRequest("UpDescribe", groupId, ["key": key, "value": value]) != nil
    }
    func upPrivateInfo(_ groupId: String, _ key: String, _ value: String) async -> Bool{
        return await gimService.imRequest("UpPrivateInfo", groupId, ["key":key, "value":value]) != nil
    }
    func updateBillboard(_ groupId: String, _ text: String) async ->Bool {
        return await gimService.imRequest("Billboard", groupId, ["text":text]) != nil
    }
    func updateShowAlias(_ groupId: String, _ value: Bool) -> Bool {
        return dbGroup.updateShowAlias(groupId, value)
    }
    func muteGroup(_ groupId: String, _ mute:Bool) async ->Bool {
        let nMute = if mute{1}else{0}
        return await gimService.imRequest("Mute", groupId, ["mute":nMute, "mode":1, "members":[]]) != nil
    }
    func muteMembers(_ osnId: String, _ members: [String], _ mute:Bool) async ->Bool {
        let nMute = if mute{1}else{0}
        return await gimService.imRequest("Mute", osnId, ["mute":nMute, "mode":0, "members":members]) != nil
    }
    func saveGroup(_ groupId: String, _ isFav:Bool) async ->Bool {
        let fav = if isFav{1}else{0}
        let data:[String:Any] = ["groupID":groupId, "status":fav]
        guard await gimService.imRequestService("SaveGroup", data) != nil else {return false}
        return setGroupFav(groupId, isFav)
    }
    func setGroupFav(_ groupId:String, _ fav:Bool)->Bool{
        if let group = getGroupInfo(groupId) {
            group.fav = fav
            return setGroupInfo(group)
        }
        return false
    }
    func joinGroup(_ groupId: String, _ reason: String, _ invitation: String) async ->[String:Any]?{
        let data:[String:Any] = ["reason":reason,"invitation":invitation]
        guard let json = await gimService.imRequest("JoinGroup", groupId, data) else {return nil}
        return gimService.getResult(json)
    }
    func createGroup(_ name: String, _ portrait: String, _ userList: [String]) async ->(String?, OspnError?) {
        let (res, err) = await ghttpService.createGroup(name, portrait, userList)
        if let err = err {
            return (nil, err)
        }
        print("createGroup: \(res!)")
        guard let groupInfo = res!["groupInfo"] as? [String:Any] else {return (nil, OspnError.Config)}
        let group = fromJson(groupInfo, nil)
        _ = setGroupInfo(group)
        var users = userList
        users.insert(gimService.mOsnId, at: 0)
        gosnMember.addInitMembers(group.groupId, users)
        return (group.groupId, nil)
    }
    func clearGroup(_ groupId: String, _ action: String) async -> Bool {
        guard await gimService.imRequest(action, groupId, ["state": action]) != nil else {return false}
        if(action == "DelGroup"){
            guard await ghttpService.deleteGroup(groupId) else {return false}
        }
        _ = gosnConversation.deleteConversation(groupId)
        _ = gosnMessage.clearMessage(groupId)
        _ = gosnMember.clearMemberInfo(groupId)
        _ = delGroupInfo(groupId)
        return true
    }
    func dismissGroup(_ groupId: String) async -> Bool {
        return await clearGroup(groupId, "DelGroup")
    }
    func quitGroup(_ groupId: String) async -> Bool{
        return await clearGroup(groupId, "QuitGroup")
    }
    func setGroupName(_ osnId: String, _ name: String) async ->Bool{
        guard await modifyGroupInfo(osnId, [ "name":name ]) else {return false}
        if let group = getGroupInfo(osnId){
            group.name = name
            return setGroupInfo(group)
        }
        return false
    }
//    func setGroupPortraitWithFile(osnId: String, file:any){
//        let url = ""
//        try{
//            let res:any = await uploadFile(file)
//            if(!res.code){
//                await setGroupPortraitWithUrl(osnId, res.data.url)
//                url = res.data.url
//            }
//        }catch(err){
//            console.log(err)
//        }
//        return url
//    }
    func setGroupPortraitWithUrl(_ osnId: String, _ url: String) async ->Bool{
        guard await modifyGroupInfo(osnId, [ "portrait": url ]) else {return false}
        if let group = getGroupInfo(osnId){
            group.portrait = url
            return setGroupInfo(group)
        }
        return false
    }

    func getGroupBillboard(_ osnId: String) ->String {
        if let group = getGroupInfo(osnId) {
            return group.billboard
        }
        return ""
    }
    func setGroupBillboard(_ osnId: String, _ billboard: String) async -> Bool{
        guard await updateBillboard(osnId, billboard) else {return false}
        if let group = getGroupInfo(osnId) {
            group.billboard = billboard
            return setGroupInfo(group)
        }
        return false
    }
    func getGroupAdmins(_ osnId: String) ->[DMCCMember]{
        let members = gosnMember.getMemberList(osnId, -1, Int.max)
        return members.filter{$0.type == OsnMemberType.Admin}
    }

    // 是否能添加成员进群组（人数限制）
    func isAddGroupMembers(_ groupId: String) -> Bool{
        if let group = getGroupInfo(groupId){
            return group.memberCount > group.maxMemberCount
        }
        return false
    }

    // 增加群组成员最大值
    func addGroupMemberMax(_ groupId: String,_ code: String) async -> Bool{
        guard let data = await ghttpService.addGroupMemberMax(groupId,code) else {return false}
        guard let res = ghttpService.getResult(data) else {return false}
        if let group = getGroupInfo(groupId){
            guard let result = res["result"] as? [String:Any] else {return false}
            guard let count = result["groupMaxMemberCount"] as? Int else {return false}
            group.maxMemberCount = count
            return setGroupInfo(group)
        }
        return false
    }

    //是否是群组成员
    func isGroupMember(){
        
    }
    func refreshGroup() async{
        return await gimService.syncGroup()
    }
    func listGroupInfo(isFav:Bool)->[DMCCGroup]{
        return dbGroup.listGroupInfo(isFav)
    }
}
let gosnGroup = OsnGroup()
